package cn.simon.free.tools.utils;

import lombok.AccessLevel;
import lombok.NoArgsConstructor;

import java.time.*;
import java.time.format.DateTimeFormatter;
import java.util.Date;

/**
 * 时间工具类
 * 1. Instant --> Date
 * 2. LocalTimeDate --> Calender
 *
 * @author simon
 * @date 2021/4/12 17:01
 * @copyright:
 * @modifier
 * @motto a no talent, people who have to study hard
 */
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class DateUtils {

    private static final String DEFAULT_FORMAT = "yyyy-MM-dd HH:mm:ss";

    /**
     * 获取当前时间
     *
     * @return
     */
    public static Date now() {
        LocalDateTime localDateTime = LocalDateTime.ofInstant(Instant.now(), ZoneId.systemDefault());
        Instant instant = localDateTime.toInstant(OffsetDateTime.now().getOffset());
        return Date.from(instant);
    }

    /**
     * 时间戳转Date
     *
     * @param timestamp
     * @return Date
     */
    public static Date now(Long timestamp) {
        LocalDateTime localDateTime = LocalDateTime.ofEpochSecond(timestamp, 0, ZoneOffset.ofHours(8));
        Instant instant = localDateTime.toInstant(OffsetDateTime.now().getOffset());
        return Date.from(instant);
    }

    /**
     * 字符串转Date
     *
     * @param date
     * @return Date
     */
    public static Date now(String date) {
        LocalDateTime localDateTime = LocalDateTime.parse(date, DateTimeFormatter.ofPattern(DEFAULT_FORMAT));
        Instant instant = localDateTime.toInstant(OffsetDateTime.now().getOffset());
        return Date.from(instant);
    }

    /**
     * 格式化当前时间(默认格式:yyyy-MM-dd HH:mm:ss)
     *
     * @param date
     * @return
     */
    public static String format(Date date) {
        return format(date, DEFAULT_FORMAT);
    }

    /**
     * 指定格式,格式化当前时间
     *
     * @param date
     * @param format
     * @return
     */
    public static String format(Date date, String format) {
        LocalDateTime localDateTime = LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
        return localDateTime.format(DateTimeFormatter.ofPattern(format));
    }

    /**
     * 添加时间,单位:年
     *
     * @param year
     * @return
     */
    public static Date addYear(Long year) {
        LocalDateTime localDateTime = getNow().plusYears(year);
        Instant instant = localDateTime.toInstant(OffsetDateTime.now().getOffset());
        return Date.from(instant);
    }

    /**
     * 给指定时间,添加时间,单位:年
     * 负数 减多少年
     * 正数 加多少年
     *
     * @param date
     * @param year
     * @return
     */
    public static Date addYear(Date date, Long year) {
        LocalDateTime localDateTime = LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault()).plusYears(year);
        return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
    }

    /**
     * 添加时间,单位:月
     *
     * @param months
     * @return
     */
    public static Date addMonth(Long months) {
        LocalDateTime localDateTime = getNow().plusMonths(months);
        Instant instant = localDateTime.toInstant(OffsetDateTime.now().getOffset());
        return Date.from(instant);
    }

    /**
     * 给指定时间,添加时间,单位:月
     * 负数 减多少月
     * 正数 加多少月
     *
     * @param date
     * @param months
     * @return
     */
    public static Date addMonth(Date date, Long months) {
        LocalDateTime localDateTime = LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault()).plusMonths(months);
        return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
    }

    /**
     * 添加时间,单位:天
     *
     * @param day
     * @return
     */
    public static Date addDay(Long day) {
        LocalDateTime localDateTime = getNow().plusDays(day);
        Instant instant = localDateTime.toInstant(OffsetDateTime.now().getOffset());
        return Date.from(instant);
    }

    /**
     * 给指定时间,添加时间,单位:天
     * 负数 减多少天
     * 正数 加多少天
     *
     * @param date
     * @param day
     * @return
     */
    public static Date addDay(Date date, Long day) {
        LocalDateTime localDateTime = LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault()).plusDays(day);
        return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
    }

    /**
     * 添加时间,单位:小时
     *
     * @param hours
     * @return
     */
    public static Date addHour(Long hours) {
        LocalDateTime localDateTime = getNow().plusMonths(hours);
        Instant instant = localDateTime.toInstant(OffsetDateTime.now().getOffset());
        return Date.from(instant);
    }

    /**
     * 给指定时间,添加时间,单位:小时
     * 负数 减多少小时
     * 正数 加多少小时
     *
     * @param date
     * @param hours
     * @return
     */
    public static Date addHour(Date date, Long hours) {
        LocalDateTime localDateTime = LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault()).plusHours(hours);
        return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
    }

    /**
     * 添加时间,单位:分钟
     *
     * @param minutes
     * @return
     */
    public static Date addMinutes(Long minutes) {
        LocalDateTime localDateTime = getNow().plusMonths(minutes);
        Instant instant = localDateTime.toInstant(OffsetDateTime.now().getOffset());
        return Date.from(instant);
    }

    /**
     * 给指定时间,添加时间,单位:分钟
     * 负数 减多少分钟
     * 正数 加多少分钟
     *
     * @param date
     * @param minutes
     * @return
     */
    public static Date addMinutes(Date date, Long minutes) {
        LocalDateTime localDateTime = LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault()).plusMinutes(minutes);
        return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
    }

    /**
     * 添加时间,单位:秒
     *
     * @param second
     * @return
     */
    public static Date addSecond(Long second) {
        LocalDateTime localDateTime = getNow().plusMonths(second);
        Instant instant = localDateTime.toInstant(OffsetDateTime.now().getOffset());
        return Date.from(instant);
    }

    /**
     * 给指定时间,添加时间,单位:秒
     * 负数 减多少秒
     * 正数 加多少秒
     *
     * @param date
     * @param second
     * @return
     */
    public static Date addSecond(Date date, Long second) {
        LocalDateTime localDateTime = LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault()).plusSeconds(second);
        return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
    }

    /**
     * 私有,获取当前时间
     *
     * @return
     */
    private static LocalDateTime getNow() {
        return LocalDateTime.ofInstant(Instant.now(), ZoneId.systemDefault());
    }
}
